home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Magazine / Online / QMail / patches / qmail-antispam4.diff < prev    next >
Encoding:
Text File  |  1997-09-26  |  10.7 KB  |  402 lines

  1. diff --unified --new-file ../qmail-1.01-unmodified/Makefile ./Makefile
  2. --- ../qmail-1.01-unmodified/Makefile    Tue Apr 15 07:05:23 1997
  3. +++ ./Makefile    Wed Sep 10 12:39:32 1997
  4. @@ -1522,12 +1522,12 @@
  5.  load qmail-smtpd.o ip.o ipme.o ipalloc.o control.o constmap.o \
  6.  received.o date822fmt.o now.o qmail.o fd.a wait.a datetime.a open.a \
  7.  getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \
  8. -str.a fs.a auto_qmail.o socket.lib
  9. +str.a fs.a auto_qmail.o dns.o dns.lib socket.lib syslog.lib
  10.      ./load qmail-smtpd ip.o ipme.o ipalloc.o control.o \
  11.      constmap.o received.o date822fmt.o now.o qmail.o fd.a \
  12.      wait.a datetime.a open.a getln.a sig.a case.a env.a \
  13.      stralloc.a alloc.a substdio.a error.a str.a fs.a \
  14. -    auto_qmail.o  `cat socket.lib`
  15. +    auto_qmail.o dns.o  `cat dns.lib` `cat socket.lib` `cat syslog.lib`
  16.  
  17.  qmail-smtpd.0: \
  18.  qmail-smtpd.8
  19. diff --unified --new-file ../qmail-1.01-unmodified/qmail-smtpd.c ./qmail-smtpd.c
  20. --- ../qmail-1.01-unmodified/qmail-smtpd.c    Tue Apr 15 07:05:23 1997
  21. +++ ./qmail-smtpd.c    Wed Sep 10 12:39:37 1997
  22. @@ -1,8 +1,20 @@
  23. +#define BADRCPT 1
  24. +#define SYSLOGGING 1
  25. +#define DENYSPAM 1
  26. +#define MAILFROMCHECK 1
  27. +#define MAILFROMDNS 1
  28. +/*zzz Version 0.9r1.0*/
  29.  #include "sig.h"
  30.  #include "readwrite.h"
  31.  #include "getln.h"
  32.  #include "stralloc.h"
  33.  #include "substdio.h"
  34. +#ifdef SYSLOGGING
  35. +#ifdef __amigaos__ /* Work around syslog.h bug.  */
  36. +#include <machine/ansi.h>
  37. +#endif
  38. +#include <syslog.h>
  39. +#endif
  40.  #include "alloc.h"
  41.  #include "auto_qmail.h"
  42.  #include "control.h"
  43. @@ -19,6 +31,9 @@
  44.  #include "env.h"
  45.  #include "now.h"
  46.  #include "exit.h"
  47. +#ifdef MAILFROMDNS
  48. +#include "dns.h"
  49. +#endif
  50.  
  51.  #define MAXHOPS 100
  52.  int timeout = 1200;
  53. @@ -26,8 +41,8 @@
  54.  char ssoutbuf[512];
  55.  substdio ssout = SUBSTDIO_FDBUF(write,1,ssoutbuf,sizeof(ssoutbuf));
  56.  
  57. -void die() { substdio_flush(&ssout); _exit(1); }
  58. -void flush() { if (substdio_flush(&ssout) == -1) _exit(1); }
  59. +void die() { substdio_flush(&ssout); closelog (); _exit(1); }
  60. +void flush() { if (substdio_flush(&ssout) == -1) { closelog (); _exit(1); } }
  61.  void out(s) char *s; { if (substdio_puts(&ssout,s) == -1) die(); }
  62.  
  63.  int timeoutread(fd,buf,n) int fd; char *buf; int n;
  64. @@ -44,9 +59,6 @@
  65.  substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf));
  66.  
  67.  
  68. -void outofmem() { out("421 out of memory (#4.3.0)\r\n"); die(); }
  69. -void sigalrm() { out("451 timeout (#4.4.2)\r\n"); die(); }
  70. -
  71.  struct qmail qqt;
  72.  stralloc greeting = {0};
  73.  int liphostok = 0;
  74. @@ -58,6 +70,11 @@
  75.  stralloc bmf = {0};
  76.  struct constmap mapbmf;
  77.  int flagbarf; /* defined if seenmail */
  78. +#ifdef BADRCPT
  79. +int brtok = 0;
  80. +stralloc brt = {0};
  81. +struct constmap mapbadrcptto;
  82. +#endif
  83.  
  84.  stralloc helohost = {0};
  85.  stralloc mailfrom = {0};
  86. @@ -71,6 +88,25 @@
  87.  char *remoteinfo;
  88.  char *local;
  89.  char *relayclient;
  90. +#ifdef DENYSPAM
  91. +char *denymail;
  92. +#endif
  93. +
  94. +void outofmem()
  95. +{
  96. +#ifdef SYSLOGGING
  97. +  syslog (LOG_ERR, "Out of memory while connected to %s!\n", remoteip);
  98. +#endif
  99. +  out("421 out of memory (#4.3.0)\r\n"); die();
  100. +}
  101. +
  102. +void sigalrm()
  103. +{
  104. +#ifdef SYSLOGGING
  105. +  syslog (LOG_INFO, "Connection to %s timed out.\n", remoteip);
  106. +#endif
  107. +  out("451 timeout (#4.4.2)\r\n"); die();
  108. +}
  109.  
  110.  void dohelo(arg) char *arg;
  111.  {
  112. @@ -90,6 +126,9 @@
  113.   remoteinfo = env_get("TCPREMOTEINFO");
  114.   relayclient = env_get("RELAYCLIENT");
  115.   dohelo(remotehost);
  116. +#ifdef DENYSPAM
  117. + denymail = env_get("DENYMAIL");
  118. +#endif
  119.  }
  120.  
  121.  void straynewline()
  122. @@ -230,16 +269,89 @@
  123.   return 1;
  124.  }
  125.  
  126. +#ifdef SYSLOGGING
  127. +
  128. +static void log_deny(m,f,t) char *m,*f,*t;
  129. +{
  130. +  syslog (LOG_INFO, "%s check failed (%s) -> (%s) [%s] (HELO %s)",
  131. +          m, f, t, remoteip, helohost.s);
  132. +} 
  133. +
  134. +#ifdef BADRCPT
  135. +static void log_brt(s,r) char *s,*r;
  136. +{
  137. +  log_deny("Bad RCPT TO:", s, r);
  138. +} 
  139. +#endif
  140. +
  141. +static void log_bmf(s,r) char *s,*r;
  142. +{
  143. +  log_deny("Bad MAIL FROM:", s, r);
  144. +} 
  145. +
  146. +static void log_ngw (char *s, char *r)
  147. +{
  148. +  log_deny ("Relayclient", s, r);
  149. +}
  150. +
  151. +static void log_helo()
  152. +{
  153. +  syslog (LOG_INFO, "Received: from %s (HELO %s)\n", remotehost, helohost.s);
  154. +} 
  155. +
  156. +#else /* not SYSLOGGING */
  157. +#define log_brt(s,r)
  158. +#define log_bmf(s,r)
  159. +#define log_deny(m,f,t)
  160. +#define log_helo()
  161. +#endif /* not SYSLOGGING */
  162. +
  163. +#ifdef MAILFROMDNS
  164. +int badmxcheck(dom) char *dom;
  165. +{
  166. +  ipalloc checkip = {0};
  167. +  int ret=0;
  168. +  stralloc checkhost = {0};
  169. +
  170. +  if (!*dom) return (DNS_HARD);
  171. +  if (!stralloc_copys(&checkhost,dom)) return (DNS_SOFT);
  172. +  
  173. +  switch (dns_mxip(&checkip,&checkhost,1))
  174. +  {
  175. +    case DNS_MEM:
  176. +    case DNS_SOFT:
  177. +         ret=DNS_SOFT;
  178. +         break;
  179. +         
  180. +    case DNS_HARD: 
  181. +         ret=DNS_HARD; 
  182. +         break;
  183. +    case 1:
  184. +         if (checkip.len <= 0) ret=DNS_HARD; 
  185. +         break;
  186. +  }
  187. +
  188. +  return (ret);
  189. +}
  190. +#endif
  191. +
  192.  int addrallowed()
  193.  {
  194.   int j;
  195.   if (!rhok) return 1;
  196.   j = byte_rchr(addr.s,addr.len,'@');
  197. +#ifdef BADRCPT
  198. + if (brtok)
  199. +    if (constmap(&mapbadrcptto, addr.s, addr.len - 1) ||
  200. +        constmap(&mapbadrcptto, addr.s + j, addr.len - j - 1))
  201. +       {log_brt(mailfrom.s,addr.s); return 0;}
  202. +#endif
  203.   if (j >= addr.len) return 1; /* can be taken care of by envnoathost */
  204.   if (constmap(&maprcpthosts,addr.s + j + 1,addr.len - j - 2)) return 1;
  205.   for (;j < addr.len;++j)
  206.     if (addr.s[j] == '.')
  207.       if (constmap(&maprcpthosts,addr.s + j,addr.len - j - 1)) return 1;
  208. + log_ngw (mailfrom.s, addr.s);
  209.   return 0;
  210.  }
  211.  
  212. @@ -251,7 +363,15 @@
  213.   if (constmap(&mapbmf,addr.s,addr.len - 1)) { flagbarf = 1; return; }
  214.   j = byte_rchr(addr.s,addr.len,'@');
  215.   if (j < addr.len)
  216. -   if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) flagbarf = 1;
  217. +#ifdef DENYSPAM 
  218. + {
  219. +#endif
  220. +   if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) { flagbarf = 1; return; }
  221. +#ifdef DENYSPAM 
  222. +   /* allow for bulkemailer@ checking */
  223. +   if (constmap(&mapbmf,addr.s, j + 1)) { flagbarf = 1; return; }
  224. + }  
  225. +#endif
  226.  }
  227.  
  228.  void smtp_greet(code) char *code; {
  229. @@ -260,7 +380,11 @@
  230.  void smtp_quit() { smtp_greet("221 "); out("\r\n"); die(); }
  231.  void smtp_help() { out("214-qmail home page: http://pobox.com/~djb/qmail.html\r\n214 send comments to qmail@pobox.com\r\n"); }
  232.  void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); }
  233. -void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
  234. +/* zzz 
  235. + void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); }
  236. +*/
  237. +void err_bmf() { out("553 syntax error, please forward to your postmaster (#5.7.1)\r\n"); }
  238. +void err_dns() { out("451 DNS temporary failure (#4.3.0)\r\n"); }
  239.  void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); }
  240.  void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); }
  241.  void err_seenmail() { out("503 one MAIL per message (#5.5.1)\r\n"); }
  242. @@ -277,10 +401,87 @@
  243.   seenmail = 0;
  244.   out("250 flushed\r\n"); }
  245.  void smtp_mail(arg) char *arg; {
  246. +int i,j; char *why;
  247.   if (seenmail) { err_seenmail(); return; }
  248.   if (!arg) { err_syntax(); return; }
  249.   if (!addrparse(arg)) { err_syntax(); return; }
  250.   bmfcheck();
  251. + if (flagbarf) { log_bmf(addr.s,""); err_bmf(); return; }
  252. +#ifdef DENYSPAM
  253. +/************
  254. +   DENYMAIL is set for this session from this client, 
  255. +             so heavy checking of mailfrom
  256. +   SPAM     -> refuse all mail
  257. +   NOBOUNCE -> refuse null mailfrom
  258. +   DNSCHECK -> validate Mailfrom domain
  259. +************/
  260. +
  261. + if (denymail)
  262. + {
  263. +    why = denymail;
  264. +    
  265. +    if (!str_diff("SPAM", denymail)) 
  266. +       flagbarf=1;
  267. +    else
  268. +      if (!addr.s[0] || !str_diff("#@[]", addr.s)) /*mjr*/
  269. +     /* if (!addr.s[0]) */
  270. +      {  
  271. +         if (!str_diff("NOBOUNCE", denymail)) 
  272. +            flagbarf=1;
  273. +      }
  274. +#ifdef MAILFROMCHECK
  275. +      else
  276. +      {
  277. +        /*why = "Invalid.Mailfrom";*/
  278. +        why = "MAIL FROM: syntax";
  279. +        if ((i=byte_chr(addr.s,addr.len,'@')) >= addr.len)
  280. +           flagbarf=1;       /* no '@' in from */
  281. +        else
  282. +        {
  283. +          /* money!@domain.TLD */
  284. +          if (addr.s[i-1] == '!') 
  285. +             flagbarf=1;
  286. +             
  287. +          /* check syntax, visual */
  288. +          if ((j = byte_rchr(addr.s+i, addr.len-i, '.')) >= addr.len-i)
  289. +             flagbarf=1;  /* curious no '.' in domain.TLD */
  290. +         
  291. +          j = addr.len-(i+1+j+1);
  292. +          if (j < 2 || j > 3)
  293. +             flagbarf=1;  /* root domain, not a country (2), nor TLD (3)*/
  294. +
  295. +#ifdef MAILFROMDNS
  296. +         if (!flagbarf)
  297. +          if (!str_diff("DNSCHECK", denymail)) 
  298. +          {
  299. +           /* check syntax, via DNS */
  300. +             why = "MAIL FROM: DNS";
  301. +             switch (badmxcheck(&addr.s[i+1]))
  302. +             {
  303. +               case 0:         break; /*valid*/
  304. +               case DNS_SOFT:    flagbarf=2; /*fail tmp*/
  305. +                                why = "(temporary) MAIL FROM: DNS";
  306. +                                break;
  307. +               case DNS_HARD:     flagbarf=1; 
  308. +                           break;
  309. +             }
  310. +          }
  311. +#endif
  312. +        }
  313. +      }
  314. +#endif
  315. +
  316. +    if (flagbarf)    
  317. +    {
  318. +      log_deny(why, addr.s, ""); 
  319. +      if (2==flagbarf)
  320. +         err_dns(); 
  321. +      else
  322. +         err_bmf();
  323. +      return;
  324. +    }
  325. + }/* denymail */
  326. +#endif   
  327.   seenmail = 1; out("250 ok\r\n");
  328.   if (!stralloc_copys(&rcptto,"")) outofmem();
  329.   if (!stralloc_copys(&mailfrom,addr.s)) outofmem();
  330. @@ -289,7 +490,6 @@
  331.   if (!seenmail) { err_wantmail(); return; }
  332.   if (!arg) { err_syntax(); return; }
  333.   if (!addrparse(arg)) { err_syntax(); return; }
  334. - if (flagbarf) { err_bmf(); return; }
  335.   if (relayclient)
  336.    {
  337.     --addr.len;
  338. @@ -301,7 +501,8 @@
  339.   out("250 ok\r\n");
  340.   if (!stralloc_cats(&rcptto,"T")) outofmem();
  341.   if (!stralloc_cats(&rcptto,addr.s)) outofmem();
  342. - if (!stralloc_0(&rcptto)) outofmem(); }
  343. + if (!stralloc_0(&rcptto)) outofmem(); 
  344. +}
  345.  
  346.  char accept_buf[FMT_ULONG];
  347.  void acceptmessage(qp) unsigned long qp;
  348. @@ -326,7 +527,8 @@
  349.   qp = qmail_qp(&qqt);
  350.   out("354 go ahead\r\n");
  351.  
  352. - received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,case_diffs(remotehost,helohost.s) ? helohost.s : 0);
  353. + received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,(r=case_diffs(remotehost,helohost.s)) ? helohost.s : 0);
  354. + if (r) log_helo();
  355.   blast(&ssin,&hops);
  356.   hops = (hops >= MAXHOPS);
  357.   if (hops) qmail_fail(&qqt);
  358. @@ -416,6 +618,15 @@
  359.       bmfok = 1;
  360.       if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die();
  361.    }
  362. +#ifdef BADRCPT
  363. + switch(control_readfile(&brt,"control/badrcptto",0))
  364. +  {
  365. +   case -1: die();
  366. +   case 1:
  367. +     brtok = 1;
  368. +     if (!constmap_init(&mapbadrcptto,brt.s,brt.len,0)) die();
  369. +  }
  370. +#endif
  371.  }
  372.  
  373.  void main()
  374. @@ -426,7 +637,18 @@
  375.   sig_alarmcatch(sigalrm);
  376.   sig_pipeignore();
  377.  
  378. - if (chdir(auto_qmail) == -1) die();
  379. +#ifdef SYSLOGGING
  380. +  openlog ("qmail-smtpd", 0, LOG_MAIL);
  381. +#endif
  382. +
  383. + if (chdir(auto_qmail) == -1)
  384. + {
  385. +#ifdef SYSLOGGING
  386. +   syslog (LOG_ERR, "Unable to switch to home directory (%s): errno=%m",
  387. +           auto_qmail);
  388. +#endif
  389. +   die();
  390. + }
  391.   getcontrols();
  392.   getenvs();
  393.  
  394. @@ -446,4 +668,7 @@
  395.     cmd.s[cmd.len++] = 0;
  396.     doit(cmd.s);
  397.    }
  398. +#ifdef SYSLOGGING
  399. +  closelog ();
  400. +#endif
  401.  }
  402.